"xn--q9jyb4c" Part 1/3

Written on July 20th, 2025

What does "xn--q9jyb4c" mean? It is text encrypted using what's known as "Punycode" meaning "みんな" (Pronounced as "Minna") or "everyone" in Japanese Hiragana. I don't know how to transition into the next part.

What is Punycode?

According to Wikipedia:

"Punycode is a representation of Unicode with the limited ASCII character subset used for Internet hostnames. Using Punycode, host names containing Unicode characters are transcoded to a subset of ASCII consisting of letters, digits, and hyphens, which is called the letter–digit–hyphen (LDH) subset."

So basically, Punycode is the internet's solution to multilingual links because they couldn't implement it in time before things became standardized. Now, they did try, but they didn't really get something set in stone before the Domain Name System (DNS) was created in 1983. Only 8 years later in 1991, would Unicode become a thing. Then allowing multilingual text to be normalized on the modern web.
Note: I did have a cool thing right here on how we went from ASCII to Unicode and then into UTF-8 but I don't know what I'm talking about so I'm just going to leave that out. But put simply: ASCII is used for the internet, Unicode is the groundwork for multilingual stuff, and UTF-8 made it smaller in size and is now the most used text standard worldwide.
The reason why these links work is because the text gets encoded (not encrypted, there's a difference.) into bytes of text that a webpage can read and your browser could display with the proper text. As a common example, "München ([the] German name for Munich) is encoded as Mnchen-3ya". The reason why we need punycode and can't just use links with multilingual characters is because of the ASCII standard which is standard with webpages. Because the internet was properly finalized before Unicode (and by extension UTF-8), we were only able to use the ASCII standard to type out links (A-Z, a-z, 0-9, and other symbols). This is where Punycode comes in by using an encoding method called "Bootstring".

What is Bootstring and how does it work?

Punycode's purpose is to allow multilingual standards by encoding ASCII (with the "xn--" prefix to indicate that the link contains Punycode) via Bootstring where it could be read and interpreted by a browser as Punycode, and displayed as normal.
As a note, "-" is used to denote that the regular ASCII text has ended and Punycode is now going to be "injected" as I will put it.
Now this guide and this guide (Credit to frereit) are both very helpful for this topic, but it is very technical and because my little brain ain't that smart, I'll try my best to figure it out. I am also using an encoder and decoder to also help me understand it better. So this is basically going to be a retelling of how it works.
So, lets work with variables. "i" is the current point that the code is on, before the first letter, the value is "0". "n" is 128. (The reason why "n" is 128 is because Punycode is for all characters above the ASCII standard that only goes to 128). If you have the word "hello" and the code is between the "l"s, "i" will have a value of "3". If I want to place a character in between the "e" and the "l", "n" would have a value of "130". When "i" is higher than "5" in this instance, the code will wrap around to the start of the work, making "i" have a value of "0". Also, every step that the code takes, including wrapping around counts as 1 step. So, if you wrapped around 3 times and "i" is equal to "2", you would be on step 20.
Forming a SLD with Punycode should go as follows: "xn--[word without special character(s)]-[code to instert special character(s)].[TLD]" (i.e. xn--mnchen-3ya.de [It redirects to muenchen.de] ). For TLDs, I believe that they have to be denoted with "xn--" if the entire TLD is in the Punycode standard. Now, here's how you encode ASCII links for to Punycode!

Single Character Encoding

Going with the example of "München", to get Punycode to type the "ü" character, you need to encode it like this:

  1. Go to the Wikipedia article for Unicode characters
  2. Look for "ü", copy decimal value. (252)
  3. Find how many steps are in a full loop around the target "Mnchen" (7 [Amount of letters + 1]), this is "y"
  4. Find what "n" would equal. (128)
  5. Find how many steps it would take from 0 to reach the desired position (1), this is "s"
  6. Subtract the decimal value and the value for "n" (124), we will call this "x".
  7. Calculate how many steps it will take to reach that point, being x*y+s=i. (124*7+1=869)
  8. With "i" equaling 869, we need to encode it.

Encoding!

(Now, this part I did use Gemini to help me figure out how it works because frereit's guide is too confusing for me. I even needed help with the first half too.)

  1. You have 869, this will be "i".
  2. Subtract "s" from "i" (868), this is "j".
  3. "j"/35 (24.8), this is "h".

[Important] side tangent!

Why 35? So, Punycode is encoded in a slightly modified version of what's known as Base-36, which is a-z and 0-9. The reason why it's 35 instead of 36 is because "a" is used as a flag to denote that if there are multiple characters in the Punycode that come before ASCII. Take note of "before ASCII" for Part 3.

Back to Encoding!

  1. Round down "h" and multiply by 35 (840), this is "k".
  2. "j"-"k" (28), this is "p".
  3. Add "s" back into "p" (29)
  4. Now, we have to go through the Punycode character list to find it. b-z is 1-25 and 0-9 is 26-35.
  5. The first digit is 3.

Another [Important] side tangent!

Here's an odd part of this. To encode, we divide by 35. If the number is still bigger than 35, you divide again. But because it isn't, this step is infinitesimal for. Because it is smaller than 35, we take the extra number (in this case 24) and find the corresponding digit in the Punycode character list for it. In this case, it's y.

  1. The first digit is "3", the second digit is "y", and the last digit is "a" because it marks the end of the character(s) that needed to be added.

So, the final text would be "xn--mnchen-3ya"!
I'll eventually talk about Multi-Character Encoding, but that's another day.